package com.tvunetworks.center.device.service.impl;

import com.tvunetworks.center.common.constant.LocalConstant;
import com.tvunetworks.center.common.exception.ServerException;
import com.tvunetworks.center.common.model.param.matrix.AddUserDeviceParam;
import com.tvunetworks.center.common.model.param.matrix.UpdateMatrixNameParam;
import com.tvunetworks.center.common.model.vo.matrix.UserPostionFlag;
import com.tvunetworks.center.common.util.JsonUtil;
import com.tvunetworks.center.common.util.MyUtil;
import com.tvunetworks.center.device.mapper.MyDeviceMapper;
import com.tvunetworks.center.device.model.MyDevice;
import com.tvunetworks.center.device.model.result.ResultConstant;
import com.tvunetworks.center.device.service.DeviceService;
import com.tvunetworks.center.device.service.MyDeviceService;
import com.tvunetworks.center.gs.model.Device;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.List;

/**
 * @program: tvucc-device
 * @description: 数据库tvu_device表对应service
 * @author lebronchen
 * @create: 2019-03-18 10:41
 **/
@Service
@Slf4j
public class MyDeviceServiceImpl implements MyDeviceService {

    @Autowired
    private MyDeviceMapper myDeviceMapper;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${redisKey.receiverCheckUDP}")
    private String receiverCheckUDPKey;
    @Value("${receiverCheckUDP.maxNum}")
    private int receiverCheckUDPKeyMaxNum;
    @Value("${receiverCheckUDP.resetNum}")
    private int receiverCheckUDPKeyResetNum;

    @Override
    public MyDevice getDeviceByPeerId(String peerId) {
        MyDevice record = new MyDevice().setPeerId(peerId);
        List<MyDevice> list = myDeviceMapper.select(record);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public String getNewDeviceName(String name) {
        MyDevice device = myDeviceMapper.getDeviceByName(name);
        if (device == null) {
            return name;
        }
        name = MyUtil.getUUID().substring(0, 15);
        return getNewDeviceName(name);
    }

    @Override
    public void addDevice(Device param) {
        Device exist = myDeviceMapper.getDeviceByPeerId(param.getPeerId());
        if (exist != null) {
            ServerException.Exception(ResultConstant.Device.PEER_ID_EXIST);
        }
        MyDevice nameExist = myDeviceMapper.getDeviceByName(param.getName());
        if (nameExist != null) {
            ServerException.Exception(ResultConstant.Device.NAME_EXIST);
        }

        MyDevice myDevice = JsonUtil.convertValue(param, MyDevice.class);
        myDevice.setId(MyUtil.getUUID());
        myDeviceMapper.insert(myDevice);
    }

    @Override
    public void updateDevice(UpdateMatrixNameParam param) {
        MyDevice myDevice = myDeviceMapper.getMyDeviceByPeerId(param.getPeerId());
        if (myDevice == null) {
            ServerException.Exception(ResultConstant.Device.DEVICE_NOT_EXIST);
        }
        if (StringUtils.equalsIgnoreCase(param.getName(), myDevice.getName())) {
            return;
        }
        MyDevice nameExist = myDeviceMapper.getDeviceByName(param.getName());
        if (nameExist != null) {
            ServerException.Exception(ResultConstant.Device.NAME_EXIST);
        }
        myDevice.setName(param.getName());
        myDeviceMapper.updateByPrimaryKey(myDevice);
    }

    @Override
    public void deleteDevice(String peerId) {
        MyDevice myDevice = myDeviceMapper.getMyDeviceByPeerId(peerId);
        if (myDevice == null) {
            ServerException.Exception(ResultConstant.Device.DEVICE_NOT_EXIST);
        }
        myDeviceMapper.deleteByPrimaryKey(myDevice.getId());
        myDeviceMapper.deleteUserDevice(peerId);
        myDeviceMapper.deleteBookmarkDevice(peerId);
    }

    @Override
    public void deleteDeviceWithSource(String peerId) {
        myDeviceMapper.deleteDeviceWithSource(peerId);
        myDeviceMapper.deleteUserDeviceWithSource(peerId);
        myDeviceMapper.deleteBookmarkDeviceWithSource(peerId);
    }

    @Override
    public List<UserPostionFlag> listUserPostionFlag(String peerId) {
        return myDeviceMapper.listUserPostionFlag(peerId);
    }

    @Override
    public void addUserDevice(AddUserDeviceParam param) {
        myDeviceMapper.addUserDevice(param);
    }

    @Override
    public void checkReceiverUDP() {
        try {
            List<String> peerIds = myDeviceMapper.listPeerIdByTypes(Arrays.asList(new String[]{LocalConstant.DeviceType.R}));
            if (CollectionUtils.isEmpty(peerIds)) {
                return;
            }

            int size = peerIds.size();
            int multiGetNum = 500;
            int start = 0;
            int end = multiGetNum;

            while (true) {
                if (end > size) {
                    end = size;
                }
                List<String> subList = peerIds.subList(start, end);
                List<Device> devices = deviceService.listCurrentDevice(subList);
                for (Device device : devices) {
                    String peerId = device.getPeerId();
                    String version = device.getVersion();
                    String status = device.getStatus();

                    if (StringUtils.isBlank(version)) {
                        continue;
                    }

                    // R 离线了清除 Redis 状态
                    if (LocalConstant.DeviceStatus.OFFLINE.equals(status)) {
                        if (stringRedisTemplate.hasKey(receiverCheckUDPKey + peerId)!=null) {
                            stringRedisTemplate.delete(receiverCheckUDPKey + peerId);
                        }
                        continue;
                    }

                    boolean tcpReport = StringUtils.contains(version, "build");
                    if (tcpReport) {
                        String inc = stringRedisTemplate.opsForValue().get(receiverCheckUDPKey + peerId);
                        if (StringUtils.isNotBlank(inc)) {
                            // 设置上限 超过上限则设置为中间值
                            Long incNum = Long.valueOf(inc);
                            if (incNum >= receiverCheckUDPKeyMaxNum) {
                                stringRedisTemplate.opsForValue().set(receiverCheckUDPKey + peerId, String.valueOf(receiverCheckUDPKeyResetNum));
                                continue;
                            }
                        }
                        Long increment = stringRedisTemplate.opsForValue().increment(receiverCheckUDPKey + peerId, 1);
                        log.error("checkReceiverUDP receiver:[{}] version:[{}] increment:[{}]", peerId, version, increment);
                    } else {
                        stringRedisTemplate.delete(receiverCheckUDPKey + peerId);
                    }
                }
                if (end == size) {
                    break;
                }
                start = end;
                end += multiGetNum;
            }
        } catch (Exception e) {
            log.error("checkReceiverUDP>>>>>>>>> Exception:[{}],e:[{}]", e);
        }
    }
}
